package com.javasoft.service.XGX.impl;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.javasoft.dao.XGX.KnowledgePointDao;
import com.javasoft.dao.XGX.PracticeDao;
import com.javasoft.entity.XGX.KnowledgePoint;
import com.javasoft.entity.XGX.Practice;
import com.javasoft.entity.XGX.Question;
import com.javasoft.service.XGX._interface.PracticeService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Random;

@Service
public class PracticeImpl extends ServiceImpl<PracticeDao, Practice> implements PracticeService {

    @Autowired
    QuestionImpl question_impl;


    @Autowired
    KnowledgePointDao knowledgePointDao;




    @Override
    public Page<Practice> getPracticePage(String subject,
                                      String knoPoint,
                                      String type,
                                      Integer difRank,
                                      Integer num,
                                      Integer currentPage,
                                      Integer pageSize) {

        List<Practice> practiceList = new ArrayList<>();

        //输入要训练的科目,可以根据知识点进行或者其他条件特训,如果只输入了科目就随机生成各个知识点的题目
        if (knoPoint == null || knoPoint.isEmpty()) {
            // 如果只输入了科目，随机生成各个知识点的题目
            practiceList =  generateRandomPracticeBySubject(subject);
        }else {
            //如果有其他的题目训练条件就根据其他条件生成题目
            practiceList = getPracticeList(subject, knoPoint, type, difRank, num);
        }

        //分页展示


        // 根据num的值确定实际要处理的记录数量，如果num为null或者小于等于0，则取全部记录，否则取num条记录
        int actualSize = num == null || num <= 0? practiceList.size() : Math.min(num, practiceList.size());
        // 使用Page的方法进行分页处理
        // 计算分页数据
        Page<Practice> showPage = new Page<>(currentPage, pageSize);
        // 计算起始索引和结束索引，用于截取practiceList中的相应部分作为当前页记录
        int startIndex = (currentPage - 1) * pageSize;
        int endIndex = Math.min(startIndex + pageSize, actualSize);
        List<Practice> subList = practiceList.subList(startIndex, endIndex);
        // 设置当前页记录、总记录数和总页数
        showPage.setRecords(subList);
        showPage.setTotal(actualSize);
        int totalPages = actualSize % pageSize == 0? actualSize / pageSize : actualSize / pageSize + 1;
        showPage.setPages(totalPages);
        return showPage;
    }


    //获取全部知识点
    private List<String> getAllKnowledgePointsForSubject(String subject){
        List<KnowledgePoint> knoPointList = new ArrayList<>();
        LambdaQueryWrapper<KnowledgePoint> wrapper = new LambdaQueryWrapper();
        wrapper.eq(KnowledgePoint::getSubject, subject);
        knoPointList = knowledgePointDao.selectList(wrapper);
        List<String> knoList = new ArrayList<>();
        for (KnowledgePoint knowledgePoint: knoPointList){
            knoList.add(knowledgePoint.getKnowledgePoint());
        }
        return knoList;
    }

    //随机生成训练题
    private List<Practice> generateRandomPracticeBySubject(String subject) {

        //获取该科目的全部知识点
        List<String> allKnowledgePoints = getAllKnowledgePointsForSubject(subject);

        // 用于存储最终生成的训练题列表
        List<Practice> randomPracticeList = new ArrayList<>();
        // 设定每个知识点最多抽取的题目数量
        int maxQuestionsPerKnowledgePoint = 3;

        Random random = new Random();
        for (String knowledgePoint : allKnowledgePoints) {
            // 根据知识点获取题目列表
            List<Practice> practiceListForKnowledgePoint = getPracticeList(subject, knowledgePoint, null, null, 100);
            if (practiceListForKnowledgePoint!= null &&!practiceListForKnowledgePoint.isEmpty()) {
                // 随机抽取一定数量的题目
                int numQuestionsToTake = Math.min(maxQuestionsPerKnowledgePoint, practiceListForKnowledgePoint.size());
                for (int i = 0; i < numQuestionsToTake; i++) {
                    int randomIndex = random.nextInt(practiceListForKnowledgePoint.size());
                    randomPracticeList.add(practiceListForKnowledgePoint.get(randomIndex));
                }
            }
        }
        //打乱顺序
        Collections.shuffle(randomPracticeList, random);
        return randomPracticeList;
    }


    @Override
    public List<Practice> getPracticeList(String subject, String knoPoint, String type, Integer difRank, Integer num) {
        if (num == null){
            num = 100;
        }
        List<Practice> practiceList = new ArrayList<>();
        List<Question> questionsList = question_impl.getQuestions(subject, knoPoint, type, difRank);
        for (Question question : questionsList) {
            Practice practice = new Practice();
            practice.setOpta(question.getOpta());
            practice.setOptb(question.getOptb());
            practice.setOptc(question.getOptc());
            practice.setOptd(question.getOptd());
            practice.setKnopoint(question.getKnopoint());
            practice.setDifrank(question.getDifrank());
            practice.setDes(question.getDes());

            practice.setType(question.getType());
            practiceList.add(practice);
        }

        return practiceList;
    }

    /**
     * 输入id列表获取题目
     * @param ids
     * @return
     */
    @Override
    public List<Practice> getPracticeListByIds(List<Long> ids) {
        List<Practice> practiceList = new ArrayList<>();
        List<Question> questionsList = question_impl.getOnlyById(ids);
        for (Question question : questionsList) {
            Practice practice = new Practice();
            practice.setOpta(question.getOpta());
            practice.setOptb(question.getOptb());
            practice.setOptc(question.getOptc());
            practice.setOptd(question.getOptd());
            practice.setKnopoint(question.getKnopoint());
            practice.setDifrank(question.getDifrank());
            practice.setDes(question.getDes());
            practice.setType(question.getType());
            practiceList.add(practice);
        }
        return practiceList;
    }


}
